home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / comm / rzsz0916.zip / ZM.C < prev    next >
C/C++ Source or Header  |  1994-08-02  |  18KB  |  879 lines

  1. /*
  2.  *   Z M . C
  3.  *    Copyright 1994 Omen Technology Inc All Rights Reserved
  4.  *    ZMODEM protocol primitives
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  * 
  15.  *
  16.  *    This version implements numerous enhancements including ZMODEM
  17.  *    Run Length Encoding and variable length headers.  These
  18.  *    features were not funded by the original Telenet development
  19.  *    contract.
  20.  * 
  21.  *  This software may be freely used for educational (didactic
  22.  *  only) purposes.  This software may also be freely used to
  23.  *  support file transfer operations to or from licensed Omen
  24.  *  Technology products.  Use with other commercial or shareware
  25.  *  programs (Crosstalk, Procomm, etc.) REQUIRES REGISTRATION.
  26.  *
  27.  *  Any programs which use part or all of this software must be
  28.  *  provided in source form with this notice intact except by
  29.  *  written permission from Omen Technology Incorporated.
  30.  * 
  31.  * Use of this software for commercial or administrative purposes
  32.  * except when exclusively limited to interfacing Omen Technology
  33.  * products requires a per port license payment of $20.00 US per
  34.  * port (less in quantity).  Use of this code by inclusion,
  35.  * decompilation, reverse engineering or any other means
  36.  * constitutes agreement to these conditions and acceptance of
  37.  * liability to license the materials and payment of reasonable
  38.  * legal costs necessary to enforce this license agreement.
  39.  *
  40.  *
  41.  *        Omen Technology Inc
  42.  *        Post Office Box 4681
  43.  *        Portland OR 97208
  44.  *
  45.  *    This code is made available in the hope it will be useful,
  46.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  47.  *    DAMAGES OF ANY KIND.
  48.  *
  49.  */
  50.  
  51. #ifndef CANFDX
  52. #include "zmodem.h"
  53. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  54. #endif
  55.  
  56. /* Globals used by ZMODEM functions */
  57. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  58. int Rxtype;        /* Type of header received */
  59. int Rxhlen;        /* Length of header received */
  60. int Rxcount;        /* Count of data bytes received */
  61. char Rxhdr[ZMAXHLEN];    /* Received header */
  62. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  63. long Rxpos;        /* Received file position */
  64. long Txpos;        /* Transmitted file position */
  65. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  66. int Crc32t;        /* Controls 32 bit CRC being sent */
  67.             /* 1 == CRC32,  2 == CRC32 + RLE */
  68. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  69.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  70. int Usevhdrs;        /* Use variable length headers */
  71. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  72. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  73. char *Altcan;        /* Alternate canit string */
  74.  
  75. static lastsent;    /* Last char we sent */
  76.  
  77. static char *frametypes[] = {
  78.     "No Response to Error Correction Request",    /* -4 */
  79.     "No Carrier Detect",        /* -3 */
  80.     "TIMEOUT",        /* -2 */
  81.     "ERROR",        /* -1 */
  82. #define FTOFFSET 4
  83.     "ZRQINIT",
  84.     "ZRINIT",
  85.     "ZSINIT",
  86.     "ZACK",
  87.     "ZFILE",
  88.     "ZSKIP",
  89.     "ZNAK",
  90.     "ZABORT",
  91.     "ZFIN",
  92.     "ZRPOS",
  93.     "ZDATA",
  94.     "ZEOF",
  95.     "ZFERR",
  96.     "ZCRC",
  97.     "ZCHALLENGE",
  98.     "ZCOMPL",
  99.     "ZCAN",
  100.     "ZFREECNT",
  101.     "ZCOMMAND",
  102.     "ZSTDERR",
  103.     "xxxxx"
  104. #define FRTYPES 22    /* Total number of frame types in this array */
  105.             /*  not including psuedo negative entries */
  106. };
  107.  
  108. static char badcrc[] = "Bad CRC";
  109.  
  110. /* Send ZMODEM binary header hdr of type type */
  111. zsbhdr(len, type, hdr)
  112. register char *hdr;
  113. {
  114.     register int n;
  115.     register unsigned short crc;
  116.  
  117. #ifndef DSZ
  118.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  119.       frametypes[type+FTOFFSET], rclhdr(hdr));
  120. #endif
  121.     if (type == ZDATA)
  122.         for (n = Znulls; --n >=0; )
  123.             xsendline(0);
  124.  
  125.     xsendline(ZPAD); xsendline(ZDLE);
  126.  
  127.     switch (Crc32t=Txfcs32) {
  128.     case 2:
  129.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  130.         flushmo();  break;
  131.     case 1:
  132.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  133.     default:
  134.         if (Usevhdrs) {
  135.             xsendline(ZVBIN);
  136.             zsendline(len);
  137.         }
  138.         else
  139.             xsendline(ZBIN);
  140.         zsendline(type);
  141.         crc = updcrc(type, 0);
  142.  
  143.         for (n=len; --n >= 0; ++hdr) {
  144.             zsendline(*hdr);
  145.             crc = updcrc((0377& *hdr), crc);
  146.         }
  147.         crc = updcrc(0,updcrc(0,crc));
  148.         zsendline(crc>>8);
  149.         zsendline(crc);
  150.     }
  151.     if (type != ZDATA)
  152.         flushmo();
  153. }
  154.  
  155.  
  156. /* Send ZMODEM binary header hdr of type type */
  157. zsbh32(len, hdr, type, flavour)
  158. register char *hdr;
  159. {
  160.     register int n;
  161.     register unsigned long crc;
  162.  
  163.     xsendline(flavour); 
  164.     if (Usevhdrs) 
  165.         zsendline(len);
  166.     zsendline(type);
  167.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  168.  
  169.     for (n=len; --n >= 0; ++hdr) {
  170.         crc = UPDC32((0377 & *hdr), crc);
  171.         zsendline(*hdr);
  172.     }
  173.     crc = ~crc;
  174.     for (n=4; --n >= 0;) {
  175.         zsendline((int)crc);
  176.         crc >>= 8;
  177.     }
  178. }
  179.  
  180. /* Send ZMODEM HEX header hdr of type type */
  181. zshhdr(len, type, hdr)
  182. register char *hdr;
  183. {
  184.     register int n;
  185.     register unsigned short crc;
  186.  
  187. #ifndef DSZ
  188.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  189.       frametypes[type+FTOFFSET], rclhdr(hdr));
  190. #endif
  191.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  192.     if (Usevhdrs) {
  193.         sendline(ZVHEX);
  194.         zputhex(len);
  195.     }
  196.     else
  197.         sendline(ZHEX);
  198.     zputhex(type);
  199.     Crc32t = 0;
  200.  
  201.     crc = updcrc(type, 0);
  202.     for (n=len; --n >= 0; ++hdr) {
  203.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  204.     }
  205.     crc = updcrc(0,updcrc(0,crc));
  206.     zputhex(crc>>8); zputhex(crc);
  207.  
  208.     /* Make it printable on remote machine */
  209.     sendline(015); sendline(0212);
  210.     /*
  211.      * Uncork the remote in case a fake XOFF has stopped data flow
  212.      */
  213.     if (type != ZFIN && type != ZACK)
  214.         sendline(021);
  215.     flushmo();
  216. }
  217.  
  218. /*
  219.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  220.  */
  221. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  222. zsdata(buf, length, frameend)
  223. register char *buf;
  224. {
  225.     register unsigned short crc;
  226.  
  227. #ifndef DSZ
  228.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  229. #endif
  230.     switch (Crc32t) {
  231.     case 1:
  232.         zsda32(buf, length, frameend);  break;
  233.     case 2:
  234.         zsdar32(buf, length, frameend);  break;
  235.     default:
  236.         crc = 0;
  237.         for (;--length >= 0; ++buf) {
  238.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  239.         }
  240.         xsendline(ZDLE); xsendline(frameend);
  241.         crc = updcrc(frameend, crc);
  242.  
  243.         crc = updcrc(0,updcrc(0,crc));
  244.         zsendline(crc>>8); zsendline(crc);
  245.     }
  246.     if (frameend == ZCRCW)
  247.         xsendline(XON);
  248.     if (frameend != ZCRCG)
  249.         flushmo();
  250. }
  251.  
  252. zsda32(buf, length, frameend)
  253. register char *buf;
  254. {
  255.     register int c;
  256.     register unsigned long crc;
  257.  
  258.     crc = 0xFFFFFFFFL;
  259.     for (;--length >= 0; ++buf) {
  260.         c = *buf & 0377;
  261.         zsendline(c);
  262.         crc = UPDC32(c, crc);
  263.     }
  264.     xsendline(ZDLE); xsendline(frameend);
  265.     crc = UPDC32(frameend, crc);
  266.  
  267.     crc = ~crc;
  268.     for (c=4; --c >= 0;) {
  269.         zsendline((int)crc);  crc >>= 8;
  270.     }
  271. }
  272.  
  273. /*
  274.  * Receive array buf of max length with ending ZDLE sequence
  275.  *  and CRC.  Returns the ending character or error code.
  276.  *  NB: On errors may store length+1 bytes!
  277.  */
  278. zrdata(buf, length)
  279. register char *buf;
  280. {
  281.     register int c;
  282.     register unsigned short crc;
  283.     register char *end;
  284.     register int d;
  285.  
  286.     switch (Crc32r) {
  287.     case 1:
  288.         return zrdat32(buf, length);
  289.     case 2:
  290.         return zrdatr32(buf, length);
  291.     }
  292.  
  293.     crc = Rxcount = 0;  end = buf + length;
  294.     while (buf <= end) {
  295.         if ((c = zdlread()) & ~0377) {
  296. crcfoo:
  297.             switch (c) {
  298.             case GOTCRCE:
  299.             case GOTCRCG:
  300.             case GOTCRCQ:
  301.             case GOTCRCW:
  302.                 crc = updcrc((d=c)&0377, crc);
  303.                 if ((c = zdlread()) & ~0377)
  304.                     goto crcfoo;
  305.                 crc = updcrc(c, crc);
  306.                 if ((c = zdlread()) & ~0377)
  307.                     goto crcfoo;
  308.                 crc = updcrc(c, crc);
  309.                 if (crc & 0xFFFF) {
  310.                     zperr(badcrc);
  311.                     return ERROR;
  312.                 }
  313.                 Rxcount = length - (end - buf);
  314. #ifndef DSZ
  315.                 vfile("zrdata: %d  %s", Rxcount,
  316.                  Zendnames[d-GOTCRCE&3]);
  317. #endif
  318.                 return d;
  319.             case GOTCAN:
  320.                 zperr("Sender Canceled");
  321.                 return ZCAN;
  322.             case TIMEOUT:
  323.                 zperr("TIMEOUT");
  324.                 return c;
  325.             default:
  326.                 garbitch(); return c;
  327.             }
  328.         }
  329.         *buf++ = c;
  330.         crc = updcrc(c, crc);
  331.     }
  332. #ifdef DSZ
  333.     garbitch(); 
  334. #else
  335.     zperr("Data subpacket too long");
  336. #endif
  337.     return ERROR;
  338. }
  339.  
  340. zrdat32(buf, length)
  341. register char *buf;
  342. {
  343.     register int c;
  344.     register unsigned long crc;
  345.     register char *end;
  346.     register int d;
  347.  
  348.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  349.     while (buf <= end) {
  350.         if ((c = zdlread()) & ~0377) {
  351. crcfoo:
  352.             switch (c) {
  353.             case GOTCRCE:
  354.             case GOTCRCG:
  355.             case GOTCRCQ:
  356.             case GOTCRCW:
  357.                 d = c;  c &= 0377;
  358.                 crc = UPDC32(c, crc);
  359.                 if ((c = zdlread()) & ~0377)
  360.                     goto crcfoo;
  361.                 crc = UPDC32(c, crc);
  362.                 if ((c = zdlread()) & ~0377)
  363.                     goto crcfoo;
  364.                 crc = UPDC32(c, crc);
  365.                 if ((c = zdlread()) & ~0377)
  366.                     goto crcfoo;
  367.                 crc = UPDC32(c, crc);
  368.                 if ((c = zdlread()) & ~0377)
  369.                     goto crcfoo;
  370.                 crc = UPDC32(c, crc);
  371.                 if (crc != 0xDEBB20E3) {
  372.                     zperr(badcrc);
  373.                     return ERROR;
  374.                 }
  375.                 Rxcount = length - (end - buf);
  376. #ifndef DSZ
  377.                 vfile("zrdat32: %d %s", Rxcount,
  378.                  Zendnames[d-GOTCRCE&3]);
  379. #endif
  380.                 return d;
  381.             case GOTCAN:
  382.                 zperr("Sender Canceled");
  383.                 return ZCAN;
  384.             case TIMEOUT:
  385.                 zperr("TIMEOUT");
  386.                 return c;
  387.             default:
  388.                 garbitch(); return c;
  389.             }
  390.         }
  391.         *buf++ = c;
  392.         crc = UPDC32(c, crc);
  393.     }
  394.     zperr("Data subpacket too long");
  395.     return ERROR;
  396. }
  397.  
  398. garbitch()
  399. {
  400.     zperr("Garbled data subpacket");
  401. }
  402.  
  403. /*
  404.  * Read a ZMODEM header to hdr, either binary or hex.
  405.  *
  406.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  407.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  408.  *   Otherwise return negative on error.
  409.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  410.  */
  411. zgethdr(hdr)
  412. char *hdr;
  413. {
  414.     register int c, n, cancount;
  415.  
  416.     n = Zrwindow + Baudrate;
  417.     Rxframeind = Rxtype = 0;
  418.  
  419. startover:
  420.     cancount = 5;
  421. again:
  422.     switch (c = readline(Rxtimeout)) {
  423.     case 021: case 0221:
  424.         goto again;
  425.     case RCDO:
  426.     case TIMEOUT:
  427.         goto fifi;
  428.     case CAN:
  429. gotcan:
  430.         if (--cancount <= 0) {
  431.             c = ZCAN; goto fifi;
  432.         }
  433.         switch (c = readline(Rxtimeout)) {
  434.         case TIMEOUT:
  435.             goto again;
  436.         case ZCRCW:
  437.             switch (readline(Rxtimeout)) {
  438.             case TIMEOUT:
  439.                 c = ERROR; goto fifi;
  440.             case RCDO:
  441.                 goto fifi;
  442.             default:
  443.                 goto agn2;
  444.             }
  445.         case RCDO:
  446.             goto fifi;
  447.         default:
  448.             break;
  449.         case CAN:
  450.             if (--cancount <= 0) {
  451.                 c = ZCAN; goto fifi;
  452.             }
  453.             goto again;
  454.         }
  455.     /* **** FALL THRU TO **** */
  456.     default:
  457. agn2:
  458.         if ( --n == 0) {
  459.             c = GCOUNT;  goto fifi;
  460.         }
  461.         goto startover;
  462.     case ZPAD:        /* This is what we want. */
  463.         break;
  464.     }
  465.     cancount = 5;
  466. splat:
  467.     switch (c = noxrd7()) {
  468.     case ZPAD:
  469.         goto splat;
  470.     case RCDO:
  471.     case TIMEOUT:
  472.         goto fifi;
  473.     default:
  474.         goto agn2;
  475.     case ZDLE:        /* This is what we want. */
  476.         break;
  477.     }
  478.  
  479.  
  480.     Rxhlen = 4;        /* Set default length */
  481.     Rxframeind = c = noxrd7();
  482.     switch (c) {
  483.     case ZVBIN32:
  484.         if ((Rxhlen = c = zdlread()) < 0)
  485.             goto fifi;
  486.         if (c > ZMAXHLEN)
  487.             goto agn2;
  488.         Crc32r = 1;  c = zrbhd32(hdr); break;
  489.     case ZBIN32:
  490.         if (Usevhdrs)
  491.             goto agn2;
  492.         Crc32r = 1;  c = zrbhd32(hdr); break;
  493.     case ZVBINR32:
  494.         if ((Rxhlen = c = zdlread()) < 0)
  495.             goto fifi;
  496.         if (c > ZMAXHLEN)
  497.             goto agn2;
  498.         Crc32r = 2;  c = zrbhd32(hdr); break;
  499.     case ZBINR32:
  500.         if (Usevhdrs)
  501.             goto agn2;
  502.         Crc32r = 2;  c = zrbhd32(hdr); break;
  503.     case RCDO:
  504.     case TIMEOUT:
  505.         goto fifi;
  506.     case ZVBIN:
  507.         if ((Rxhlen = c = zdlread()) < 0)
  508.             goto fifi;
  509.         if (c > ZMAXHLEN)
  510.             goto agn2;
  511.         Crc32r = 0;  c = zrbhdr(hdr); break;
  512.     case ZBIN:
  513.         if (Usevhdrs)
  514.             goto agn2;
  515.         Crc32r = 0;  c = zrbhdr(hdr); break;
  516.     case ZVHEX:
  517.         if ((Rxhlen = c = zgethex()) < 0)
  518.             goto fifi;
  519.         if (c > ZMAXHLEN)
  520.             goto agn2;
  521.         Crc32r = 0;  c = zrhhdr(hdr); break;
  522.     case ZHEX:
  523.         if (Usevhdrs)
  524.             goto agn2;
  525.         Crc32r = 0;  c = zrhhdr(hdr); break;
  526.     case CAN:
  527.         goto gotcan;
  528.     default:
  529.         goto agn2;
  530.     }
  531.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  532.         hdr[n] = 0;
  533.     Rxpos = hdr[ZP3] & 0377;
  534.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  535.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  536.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  537. fifi:
  538.     switch (c) {
  539.     case GOTCAN:
  540.         c = ZCAN;
  541.     /* **** FALL THRU TO **** */
  542.     case ZNAK:
  543.     case ZCAN:
  544.     case ERROR:
  545.     case TIMEOUT:
  546.     case RCDO:
  547.     case GCOUNT:
  548.         zperr("Got %s", frametypes[c+FTOFFSET]);
  549.     /* **** FALL THRU TO **** */
  550. #ifndef DSZ
  551.     default:
  552.         if (c >= -4 && c <= FRTYPES)
  553.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  554.               frametypes[c+FTOFFSET], Rxpos);
  555.         else
  556.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  557. #endif
  558.     }
  559.     /* Use variable length headers if we got one */
  560.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  561.         Usevhdrs = 1;
  562.     return c;
  563. }
  564.  
  565. /* Receive a binary style header (type and position) */
  566. zrbhdr(hdr)
  567. register char *hdr;
  568. {
  569.     register int c, n;
  570.     register unsigned short crc;
  571.  
  572.     if ((c = zdlread()) & ~0377)
  573.         return c;
  574.     Rxtype = c;
  575.     crc = updcrc(c, 0);
  576.  
  577.     for (n=Rxhlen; --n >= 0; ++hdr) {
  578.         if ((c = zdlread()) & ~0377)
  579.             return c;
  580.         crc = updcrc(c, crc);
  581.         *hdr = c;
  582.     }
  583.     if ((c = zdlread()) & ~0377)
  584.         return c;
  585.     crc = updcrc(c, crc);
  586.     if ((c = zdlread()) & ~0377)
  587.         return c;
  588.     crc = updcrc(c, crc);
  589.     if (crc & 0xFFFF) {
  590.         zperr(badcrc);
  591.         return ERROR;
  592.     }
  593. #ifdef ZMODEM
  594.     Protocol = ZMODEM;
  595. #endif
  596.     Zmodem = 1;
  597.     return Rxtype;
  598. }
  599.  
  600. /* Receive a binary style header (type and position) with 32 bit FCS */
  601. zrbhd32(hdr)
  602. register char *hdr;
  603. {
  604.     register int c, n;
  605.     register unsigned long crc;
  606.  
  607.     if ((c = zdlread()) & ~0377)
  608.         return c;
  609.     Rxtype = c;
  610.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  611. #ifdef DEBUGZ
  612.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  613. #endif
  614.  
  615.     for (n=Rxhlen; --n >= 0; ++hdr) {
  616.         if ((c = zdlread()) & ~0377)
  617.             return c;
  618.         crc = UPDC32(c, crc);
  619.         *hdr = c;
  620. #ifdef DEBUGZ
  621.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  622. #endif
  623.     }
  624.     for (n=4; --n >= 0;) {
  625.         if ((c = zdlread()) & ~0377)
  626.             return c;
  627.         crc = UPDC32(c, crc);
  628. #ifdef DEBUGZ
  629.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  630. #endif
  631.     }
  632.     if (crc != 0xDEBB20E3) {
  633.         zperr(badcrc);
  634.         return ERROR;
  635.     }
  636. #ifdef ZMODEM
  637.     Protocol = ZMODEM;
  638. #endif
  639.     Zmodem = 1;
  640.     return Rxtype;
  641. }
  642.  
  643.  
  644. /* Receive a hex style header (type and position) */
  645. zrhhdr(hdr)
  646. char *hdr;
  647. {
  648.     register int c;
  649.     register unsigned short crc;
  650.     register int n;
  651.  
  652.     if ((c = zgethex()) < 0)
  653.         return c;
  654.     Rxtype = c;
  655.     crc = updcrc(c, 0);
  656.  
  657.     for (n=Rxhlen; --n >= 0; ++hdr) {
  658.         if ((c = zgethex()) < 0)
  659.             return c;
  660.         crc = updcrc(c, crc);
  661.         *hdr = c;
  662.     }
  663.     if ((c = zgethex()) < 0)
  664.         return c;
  665.     crc = updcrc(c, crc);
  666.     if ((c = zgethex()) < 0)
  667.         return c;
  668.     crc = updcrc(c, crc);
  669.     if (crc & 0xFFFF) {
  670.         zperr(badcrc); return ERROR;
  671.     }
  672.     c = readline(Rxtimeout);
  673.     if (c < 0)
  674.         return c;
  675.     c = readline(Rxtimeout);
  676. #ifdef ZMODEM
  677.     Protocol = ZMODEM;
  678. #endif
  679.     Zmodem = 1;
  680.     if (c < 0)
  681.         return c;
  682.     return Rxtype;
  683. }
  684.  
  685. /* Send a byte as two hex digits */
  686. zputhex(c)
  687. register int c;
  688. {
  689.     static char    digits[]    = "0123456789abcdef";
  690.  
  691. #ifdef DEBUGZ
  692.     if (Verbose>8)
  693.         vfile("zputhex: %02X", c);
  694. #endif
  695.     sendline(digits[(c&0xF0)>>4]);
  696.     sendline(digits[(c)&0xF]);
  697. }
  698.  
  699. /*
  700.  * Send character c with ZMODEM escape sequence encoding.
  701.  */
  702. zsendline(c)
  703. register c;
  704. {
  705.     switch (c &= 0377) {
  706.     case 0377:
  707.         lastsent = c;
  708.         if (Zctlesc || Zsendmask[32]) {
  709.             xsendline(ZDLE);  c = ZRUB1;
  710.         }
  711.         xsendline(c);
  712.         break;
  713.     case ZDLE:
  714.         xsendline(ZDLE);  xsendline (lastsent = (c ^= 0100));
  715.         break;
  716.     case 021: case 023:
  717.     case 0221: case 0223:
  718.         xsendline(ZDLE);  c ^= 0100;  xsendline(lastsent = c);
  719.         break;
  720.     default:
  721.         if (((c & 0140) == 0) && (Zctlesc || Zsendmask[c & 037])) {
  722.             xsendline(ZDLE);  c ^= 0100;
  723.         }
  724.         xsendline(lastsent = c);
  725.     }
  726. }
  727.  
  728. /* Decode two lower case hex digits into an 8 bit byte value */
  729. zgethex()
  730. {
  731.     register int c;
  732.  
  733.     c = zgeth1();
  734. #ifdef DEBUGZ
  735.     if (Verbose>8)
  736.         vfile("zgethex: %02X", c);
  737. #endif
  738.     return c;
  739. }
  740. zgeth1()
  741. {
  742.     register int c, n;
  743.  
  744.     if ((c = noxrd7()) < 0)
  745.         return c;
  746.     n = c - '0';
  747.     if (n > 9)
  748.         n -= ('a' - ':');
  749.     if (n & ~0xF)
  750.         return ERROR;
  751.     if ((c = noxrd7()) < 0)
  752.         return c;
  753.     c -= '0';
  754.     if (c > 9)
  755.         c -= ('a' - ':');
  756.     if (c & ~0xF)
  757.         return ERROR;
  758.     c += (n<<4);
  759.     return c;
  760. }
  761.  
  762. /*
  763.  * Read a byte, checking for ZMODEM escape encoding
  764.  *  including CAN*5 which represents a quick abort
  765.  */
  766. zdlread()
  767. {
  768.     register int c;
  769.  
  770. again:
  771.     /* Quick check for non control characters */
  772.     if ((c = readline(Rxtimeout)) & 0140)
  773.         return c;
  774.     switch (c) {
  775.     case ZDLE:
  776.         break;
  777.     case 023:
  778.     case 0223:
  779.     case 021:
  780.     case 0221:
  781.         goto again;
  782.     default:
  783.         if (Zctlesc && !(c & 0140)) {
  784.             goto again;
  785.         }
  786.         return c;
  787.     }
  788. again2:
  789.     if ((c = readline(Rxtimeout)) < 0)
  790.         return c;
  791.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  792.         return c;
  793.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  794.         return c;
  795.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  796.         return c;
  797.     switch (c) {
  798.     case CAN:
  799.         return GOTCAN;
  800.     case ZCRCE:
  801.     case ZCRCG:
  802.     case ZCRCQ:
  803.     case ZCRCW:
  804.         return (c | GOTOR);
  805.     case ZRUB0:
  806.         return 0177;
  807.     case ZRUB1:
  808.         return 0377;
  809.     case 023:
  810.     case 0223:
  811.     case 021:
  812.     case 0221:
  813.         goto again2;
  814.     default:
  815.         if (Zctlesc && ! (c & 0140)) {
  816.             goto again2;
  817.         }
  818.         if ((c & 0140) ==  0100)
  819.             return (c ^ 0100);
  820.         break;
  821.     }
  822.     if (Verbose>1)
  823.         zperr("Bad escape sequence %x", c);
  824.     return ERROR;
  825. }
  826.  
  827. /*
  828.  * Read a character from the modem line with timeout.
  829.  *  Eat parity, XON and XOFF characters.
  830.  */
  831. noxrd7()
  832. {
  833.     register int c;
  834.  
  835.     for (;;) {
  836.         if ((c = readline(Rxtimeout)) < 0)
  837.             return c;
  838.         switch (c &= 0177) {
  839.         case XON:
  840.         case XOFF:
  841.             continue;
  842.         default:
  843.             if (Zctlesc && !(c & 0140))
  844.                 continue;
  845.         case '\r':
  846.         case '\n':
  847.         case ZDLE:
  848.             return c;
  849.         }
  850.     }
  851.     /* NOTREACHED */
  852. }
  853.  
  854. /* Store long integer pos in Txhdr */
  855. stohdr(pos)
  856. long pos;
  857. {
  858.     Txhdr[ZP0] = pos;
  859.     Txhdr[ZP1] = pos>>8;
  860.     Txhdr[ZP2] = pos>>16;
  861.     Txhdr[ZP3] = pos>>24;
  862. }
  863.  
  864. /* Recover a long integer from a header */
  865. long
  866. rclhdr(hdr)
  867. register char *hdr;
  868. {
  869.     register long l;
  870.  
  871.     l = (hdr[ZP3] & 0377);
  872.     l = (l << 8) | (hdr[ZP2] & 0377);
  873.     l = (l << 8) | (hdr[ZP1] & 0377);
  874.     l = (l << 8) | (hdr[ZP0] & 0377);
  875.     return l;
  876. }
  877.  
  878. /* End of zm.c */
  879.